/*
 * Copyright 2007 Gergely Kis
 * Copyright 2006 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.client.impl;


import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;

import org.jdom.Parent;

/**
 * Base implementation of {@link com.google.gwt.user.client.impl.DomImpl} shared
 * by those browsers that come a bit closer to supporting a common standard (ie,
 * not IE).
 */
abstract class DOMImplStandard extends DOMImpl {

  public boolean compare(Element elem1, Element elem2) {
    return elem1 == elem2;
  }

  public Element createInputRadioElement(String group) {
    ElementImpl e = (ElementImpl) createInputElement("radio");
    e.setAttribute("name", group);
    return (Element) e;
  }

  public Element eventGetTarget(Event evt) {
    EventImpl e = (EventImpl) evt;
    return e.getTarget();
  }

  public Element eventGetToElement(Event evt) {
    throw new RuntimeException("Not supported");
  }

  public void eventPreventDefault(Event evt) {
    ((EventImpl) evt).preventDefault();
  }
  public String eventToString(Event evt) {
    throw new RuntimeException("Not supported");
  }

  public Element getChild(Element elem, int index) {
    ElementImpl e = (ElementImpl) elem;
    if (e.getChildren() == null || e.getChildren().size() <= index) return null;
    return (Element) e.getChildren().get(index);    
  }

  public int getChildCount(Element elem) {
    ElementImpl e = (ElementImpl) elem;
    return e.getChildren().size();
  }

  public int getChildIndex(Element parent, Element toFind) {
    ElementImpl p = (ElementImpl) parent;
    ElementImpl t = (ElementImpl) toFind;
    return p.getChildren().indexOf(t);
  }

  public Element getFirstChild(Element elem) {
    ElementImpl e = (ElementImpl) elem;
    if (e.getChildren() == null || e.getChildren().size() <= 0) return null;
    return (Element) e.getChildren().get(0);
  }

  public Element getNextSibling(Element elem) {
    ElementImpl e = (ElementImpl) elem;
    try {
      ElementImpl p = (ElementImpl) e.getParent();
      return (Element) p.getChildren().get(p.getChildren().indexOf(e)+1);
    }
    catch (Exception ex) {
      // Either no parent -> which means no siblings, or there are no more siblings.
    }
    return null;
  }

  public Element getParent(Element elem) {
      // FIXME: Check whether we should also consider the Document itself, not just the root element.
      return (Element) ((ElementImpl) elem).getParentElement();
    }

  public String iframeGetSrc(Element elem) {
    ElementImpl e = (ElementImpl) elem;
    return e.getAttributeValue("src");
  }

  public void init() {
    // Empty for now.
    // In Javascript the DOM Event listeners were hooked here.
  }
  public void insertChild(Element parent, Element toAdd, int index) {
    ElementImpl p = (ElementImpl) parent;
    ElementImpl e = (ElementImpl) toAdd;
    if (e.getParent() != null) {
    	e.getParent().removeContent(e);
    }
    p.addContent(index, e);
  }

  public boolean isOrHasChild(Element parent, Element child) {
    ElementImpl p = (ElementImpl) parent;
    ElementImpl c = (ElementImpl) child;
    while (c != null) {
      if (c == p) {
        return true;
      }
      Parent par = c.getParent();
      if (!(par instanceof org.jdom.Element)) {
        c = null;
      } else {
        c = (ElementImpl) par;
      }
    }
    return false;
  }

  public void releaseCapture(Element elem) {
    throw new RuntimeException("Not supported");
  }

  public void setCapture(Element elem) {
    throw new RuntimeException("Not supported");
  }

  public void sinkEvents(Element elem, int bits) {
    ElementImpl e = (ElementImpl) elem;
    e.setEventBits(bits);
  }
  
  /*-{
  }
    elem.__eventBits = bits;

    elem.onclick       = (bits & 0x00001) ? $wnd.__dispatchEvent : null;
    elem.ondblclick    = (bits & 0x00002) ? $wnd.__dispatchEvent : null;
    elem.onmousedown   = (bits & 0x00004) ? $wnd.__dispatchEvent : null;
    elem.onmouseup     = (bits & 0x00008) ? $wnd.__dispatchEvent : null;
    elem.onmouseover   = (bits & 0x00010) ? $wnd.__dispatchEvent : null;
    elem.onmouseout    = (bits & 0x00020) ? $wnd.__dispatchEvent : null;
    elem.onmousemove   = (bits & 0x00040) ? $wnd.__dispatchEvent : null;
    elem.onkeydown     = (bits & 0x00080) ? $wnd.__dispatchEvent : null;
    elem.onkeypress    = (bits & 0x00100) ? $wnd.__dispatchEvent : null;
    elem.onkeyup       = (bits & 0x00200) ? $wnd.__dispatchEvent : null;
    elem.onchange      = (bits & 0x00400) ? $wnd.__dispatchEvent : null;
    elem.onfocus       = (bits & 0x00800) ? $wnd.__dispatchEvent : null;
    elem.onblur        = (bits & 0x01000) ? $wnd.__dispatchEvent : null;
    elem.onlosecapture = (bits & 0x02000) ? $wnd.__dispatchEvent : null;
    elem.onscroll      = (bits & 0x04000) ? $wnd.__dispatchEvent : null;
    elem.onload        = (bits & 0x08000) ? $wnd.__dispatchEvent : null;
    elem.onerror       = (bits & 0x10000) ? $wnd.__dispatchEvent : null;
  }-*/;

  public String toString(Element elem) {
    ElementImpl e = (ElementImpl) elem;
    return e.toString();
  }
}
